﻿using System;
using System.Collections.Generic;
using System.Windows.Media.Media3D;
using LFSRecord2.Misc;

namespace LFSRecord2.Model
{
    public class CompLayerNull : CompLayerBase
    {
        public enum PropertyTypes
        {
            Anchor = 0,
            Position = 1,
            Scale = 2,
            Orientation = 3,
            RotateX = 4,
            RotateY = 5,
            RotateZ = 6,
        }

        [Flags]
        public enum PropertyTypesFlags
        {
            None = 0,
            Anchor = 1,
            Position = 2,
            Scale = 4,
            Orientation = 8,
            RotateX = 16,
            RotateY = 32,
            RotateZ = 64,
        }

        public CompLayerNull(short layerIndex, string layerName)
        {
            UniqueID = MathHelper.UniqueID;
            LayerIndex = layerIndex;
            LayerType = CompLayerTypes.Null;
            LayerName = layerName;
            LayerObjectMesh = new CompLayerNullMesh();

            IsActiveCamera = false;

            // Setup properties
            Properties = new List<CompLayerPropertyBase>(6);
            Properties.Add(new CompLayerPropertyPoint3D(this, 0, "Anchor", new Point3D(), LayerPropertyValueMeaning.Generic));
            Properties.Add(new CompLayerPropertyPoint3D(this, 1, "Position", new Point3D(), LayerPropertyValueMeaning.Generic, true));
            Properties.Add(new CompLayerPropertyPoint3D(this, 2, "Scale", new Point3D(1.0d, 1.0d, 1.0d), LayerPropertyValueMeaning.Percent));
            Properties.Add(new CompLayerPropertyPoint3D(this, 3, "Orientation", new Point3D(0, 0, 0), LayerPropertyValueMeaning.Degrees, false));
            Properties.Add(new CompLayerPropertyDouble(this, 4, "Rotate X", 0, LayerPropertyValueMeaning.Degrees));
            Properties.Add(new CompLayerPropertyDouble(this, 5, "Rotate Y", 0, LayerPropertyValueMeaning.Degrees));
            Properties.Add(new CompLayerPropertyDouble(this, 6, "Rotate Z", 0, LayerPropertyValueMeaning.Degrees));

            ((CompLayerPropertyPoint3D)Properties[(int)PropertyTypes.Scale]).HasValueLock = true;
            ((CompLayerPropertyPoint3D)Properties[(int)PropertyTypes.Scale]).ValueLock = true;

            SetCurrentTransformMatrix();
        }

        public override Matrix3D GetTransformMatrixAtFrame(int frame)
        {
            Point3D position = (Point3D)((CompLayerPropertyPoint3D)Properties[(int)PropertyTypes.Position]).GetValueAtFrame(frame);
            Point3D anchor = (Point3D)((CompLayerPropertyPoint3D)Properties[(int)PropertyTypes.Anchor]).GetValueAtFrame(frame);
            double phi = (double)((CompLayerPropertyDouble)Properties[(int)PropertyTypes.RotateX]).GetValueAtFrame(frame);
            double theta = (double)((CompLayerPropertyDouble)Properties[(int)PropertyTypes.RotateY]).GetValueAtFrame(frame);
            double psi = (double)((CompLayerPropertyDouble)Properties[(int)PropertyTypes.RotateZ]).GetValueAtFrame(frame);

            Matrix3D mTr = new Matrix3D();
            Point3D orientation = (Point3D)((CompLayerPropertyPoint3D)Properties[(int)PropertyTypes.Orientation]).GetValueAtFrame(frame);

            // Orientate
            mTr.RotateAt(new Quaternion(new Vector3D(0, 1, 0), orientation.Y), anchor);
            mTr.RotateAt(new Quaternion(new Vector3D(0, 0, 1), orientation.Z), anchor);
            mTr.RotateAt(new Quaternion(new Vector3D(1, 0, 0), -orientation.X), anchor);

            // Rotate
            mTr.RotateAt(new Quaternion(new Vector3D(0, 1, 0), theta), anchor);
            mTr.RotateAt(new Quaternion(new Vector3D(0, 0, 1), psi), anchor);
            mTr.RotateAt(new Quaternion(new Vector3D(1, 0, 0), -phi), anchor);

            // Scale the matrix
            Point3D scale = (Point3D)((CompLayerPropertyPoint3D)Properties[(int)PropertyTypes.Scale]).GetValueAtFrame(frame);
            mTr.ScaleAt(new Vector3D(scale.X, scale.Y, scale.Z), anchor);

            // Translate the matrix
            mTr.Translate(Point3D.Subtract(position, anchor));

            return mTr;
        }

        public override void SetMeshLookAtPointAtFrame(int frame)
        {
        }

        public override void SetMeshCenterPointAtFrame(int frame)
        {
            LayerObjectMesh.CenterPoint = (Point3D)((CompLayerPropertyPoint3D)Properties[(int)PropertyTypes.Anchor]).GetValueAtFrame(frame);
        }

        public override void RemoveParentingJump(CompLayerBase parentLayer)
        {
        }

        public override void AddParentingJump()
        {
        }
    }
}
